package com.wzz.controller;

import com.wzz.entity.ExamRecord;
import com.wzz.entity.Question;
import com.wzz.entity.QuestionBank;
import com.wzz.exception.BusinessException;
import com.wzz.exception.CommonErrorCode;
import com.wzz.mapper.DataMapper;
import com.wzz.service.ExamRecordService;
import com.wzz.service.ExamService;
import com.wzz.service.QuestionBankService;
import com.wzz.service.QuestionService;
import com.wzz.service.UserService;
import com.wzz.utils.JwtUtils;
import com.wzz.utils.OSSUtil;
import com.wzz.utils.kms.KMeans;
import com.wzz.utils.kms.Point;
import com.wzz.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author wzz
 * @implNote 10/24 15:42
 */
@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
@Api(tags = "老师权限相关的接口")
@RequestMapping(value = "/teacher")
public class TeacherController {

    private final OSSUtil ossUtil;

    private final ExamService examService;

    private final UserService userService;

    private final QuestionService questionService;

    private final ExamRecordService examRecordService;

    private final QuestionBankService questionBankService;


    @Autowired
    private DataMapper dataMapper;

    @GetMapping("/getQuestionBank")
    @ApiOperation("获取所有题库信息")
    public CommonResult<List<QuestionBank>> getQuestionBank() {
        return CommonResult.<List<QuestionBank>>builder()
                .data(questionBankService.getAllQuestionBanks())
                .build();
    }

    @GetMapping("/getQuestion")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "questionType", value = "问题类型", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "questionBank", value = "问题所属题库", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "questionContent", value = "问题内容", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "pageNo", value = "页面数", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "页面大小", required = true, dataType = "int", paramType = "query")
    })
    @ApiOperation("获取题目信息,可分页 ----> 查询条件(可无)(questionType,questionBank,questionContent),必须有的(pageNo,pageSize)")
    public CommonResult<PageResponse<Question>> getQuestion(@RequestParam(required = false) String questionType,
                                                            @RequestParam(required = false) String questionBank,
                                                            @RequestParam(required = false) String questionContent,
                                                            Integer pageNo, Integer pageSize) {
        return CommonResult.<PageResponse<Question>>builder()
                .data(questionService.getQuestion(questionType, questionBank, questionContent, pageNo, pageSize))
                .build();
    }

    @GetMapping("/deleteQuestion")
    @ApiOperation("根据id批量删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "questionIds", value = "问题id的字符串以逗号分隔", required = true, dataType = "string", paramType = "query")
    })
    public CommonResult<Void> deleteQuestion(String questionIds) {
        questionService.deleteQuestionByIds(questionIds);
        return CommonResult.<Void>builder()
                .build();
    }

    @GetMapping("/addBankQuestion")
    @ApiOperation("将问题加入题库")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "questionIds", value = "问题id的字符串以逗号分隔", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "banks", value = "题库id的字符串以逗号分隔", required = true, dataType = "string", paramType = "query")
    })
    public CommonResult<String> addBankQuestion(String questionIds, String banks) {
        questionBankService.addQuestionToBank(questionIds, banks);
        return CommonResult.<String>builder()
                .build();
    }

    @GetMapping("/removeBankQuestion")
    @ApiOperation("将问题从题库移除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "questionIds", value = "问题id的字符串以逗号分隔", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "banks", value = "题库id的字符串以逗号分隔", required = true, dataType = "string", paramType = "query")
    })
    public CommonResult<Void> removeBankQuestion(String questionIds, String banks) {
        questionBankService.removeBankQuestion(questionIds, banks);
        return CommonResult.<Void>builder()
                .build();
    }

    @PostMapping("/uploadQuestionImage")
    @ApiOperation("接受前端上传的图片,返回上传图片地址")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "图片文件", required = true, dataType = "file", paramType = "body")
    })
    public CommonResult<String> uploadQuestionImage(MultipartFile file) throws Exception {
        log.info("开始上传文件: {}", file.getOriginalFilename());
        String fileName = file.getOriginalFilename();  // 文件名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));  // 后缀名
        String filePath = "D://exam//"; // 上传后的路径
        fileName = UUID.randomUUID() + suffixName; // 新文件名
        File dest = new File(filePath + fileName);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String filename = "http://localhost:8888/exam/" + fileName;
        return CommonResult.<String>builder()
                .data(filename)
                .message("上传成功")
                .build();
    }

    @PostMapping("/addQuestion")
    @ApiOperation("添加试题")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "questionVo", value = "问题的vo视图对象", required = true, dataType = "questionVo", paramType = "body")
    })
    public CommonResult<Void> addQuestion(@RequestBody @Valid QuestionVo questionVo) {
        questionService.addQuestion(questionVo);
        return CommonResult.<Void>builder().build();
    }

    @PostMapping("/updateQuestion")
    @ApiOperation("更新试题")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "questionVo", value = "问题的vo视图对象", required = true, dataType = "questionVo", paramType = "body")
    })
    public CommonResult<Void> updateQuestion(@RequestBody @Valid QuestionVo questionVo) {
        questionService.updateQuestion(questionVo);
        return CommonResult.<Void>builder()
                .build();
    }

    @GetMapping("/deleteQuestionBank")
    @ApiOperation("删除题库并去除所有题目中的包含此题库的信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "删除题库的id字符串逗号分隔", required = true, dataType = "string", paramType = "query")
    })
    public CommonResult<Void> deleteQuestionBank(String ids) {
        questionBankService.deleteQuestionBank(ids);
        return CommonResult.<Void>builder()
                .build();
    }

    @PostMapping("/addQuestionBank")
    @ApiOperation("添加题库信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "questionBank", value = "题库的实体对象", required = true, dataType = "questionBank", paramType = "body")
    })
    public CommonResult<Void> addQuestionBank(@RequestBody QuestionBank questionBank) {
        questionBankService.addQuestionBank(questionBank);
        return CommonResult.<Void>builder()
                .build();
    }

    @GetMapping("/operationExam/{type}")
    @ApiOperation("操作考试的信息表(type 1启用 2禁用 3删除)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "操作类型", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "ids", value = "操作的考试id集合", required = true, dataType = "string", paramType = "query")
    })
    public CommonResult<Void> operationExam(@PathVariable("type") Integer type, String ids) {
        examService.operationExam(type, ids);
        return CommonResult.<Void>builder()
                .build();
    }

    @PostMapping("/addExamByBank")
    @ApiOperation("根据题库添加考试")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "addExamByBankVo", value = "根据题库添加考试vo对象", required = true, dataType = "addExamByBankVo", paramType = "body")
    })
    public CommonResult<Void> addExamByBank(@RequestBody @Valid AddExamByBankVo addExamByBankVo, HttpServletRequest request) {
        TokenVo userInfoByToken = JwtUtils.getUserInfoByToken(request);
        if (userInfoByToken.getClassId() == null){
            throw new BusinessException(CommonErrorCode.E_1001231);
        }
        addExamByBankVo.setClassId(userInfoByToken.getClassId());
        examService.addExamByBank(addExamByBankVo);
        return CommonResult.<Void>builder()
                .build();
    }

    @PostMapping("/addExamByQuestionList")
    @ApiOperation("根据题目列表添加考试")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "addExamByQuestionVo", value = "通过题目列表添加考试的vo对象", required = true, dataType = "addExamByQuestionVo", paramType = "body")
    })
    public CommonResult<Void> addExamByQuestionList(@RequestBody @Valid AddExamByQuestionVo addExamByQuestionVo,HttpServletRequest request) {
        TokenVo userInfoByToken = JwtUtils.getUserInfoByToken(request);
        if (userInfoByToken.getClassId() == null){
            throw new BusinessException(CommonErrorCode.E_1001231);
        }
        addExamByQuestionVo.setClassId(userInfoByToken.getClassId());
        examService.addExamByQuestionList(addExamByQuestionVo);
        return CommonResult.<Void>builder()
                .build();
    }

    @PostMapping("/updateExamInfo")
    @ApiOperation("更新考试的信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "addExamByQuestionVo", value = "通过题目列表添加考试的vo对象", required = true, dataType = "addExamByQuestionVo", paramType = "body")
    })
    public CommonResult<Void> updateExamInfo(@RequestBody AddExamByQuestionVo addExamByQuestionVo) {
        examService.updateExamInfo(addExamByQuestionVo);
        return CommonResult.<Void>builder()
                .message("更新成功")
                .build();
    }

    @GetMapping("/getExamRecord")
    @ApiOperation("获取考试记录信息,(pageNo,pageSize)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examId", value = "考试id", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageNo", value = "页面数", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "页面大小", required = true, dataType = "int", paramType = "query")
    })
    public CommonResult<PageResponse<ExamRecord>> getExamRecord(@RequestParam(required = false) Integer examId, Integer pageNo, Integer pageSize,HttpServletRequest request) {
        TokenVo userInfoByToken = JwtUtils.getUserInfoByToken(request);
        //学生处理
        if (userInfoByToken.getRoleId() == 1){
            if (userInfoByToken.getClassId() == null){
                throw new BusinessException(CommonErrorCode.E_1001231);
            }

        }
        //老师处理
        if (userInfoByToken.getRoleId() == 2){
            if (userInfoByToken.getClassId() == null){
                throw new BusinessException(CommonErrorCode.E_1001231);
            }
        }
        //管理员处理
        if (userInfoByToken.getRoleId() == 3){
            return CommonResult.<PageResponse<ExamRecord>>builder()
                    .data(examRecordService.getExamRecord(examId, pageNo, pageSize,null))
                    .build();
        }
        return CommonResult.<PageResponse<ExamRecord>>builder()
                .data(examRecordService.getExamRecord(examId, pageNo, pageSize,userInfoByToken.getClassId()))
                .build();
    }

    @GetMapping("/getUserById/{userId}")
    @ApiOperation("根据用户id查询用户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, dataType = "int", paramType = "query")
    })
    public CommonResult<UserInfoVo> getUserById(@PathVariable Integer userId) {
        return CommonResult.<UserInfoVo>builder()
                .data(userService.getUserInfoById(userId))
                .build();
    }

    @GetMapping("/getUserByIds")
    @ApiOperation("根据用户ids查询用户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userIds", value = "用户ids", required = true, dataType = "int", paramType = "query")
    })
    public CommonResult<List<UserInfoVo>> getUserByIds(@RequestParam("userIds") List<Integer> userIds) {
        return CommonResult.<List<UserInfoVo>>builder()
                .data(userService.getUserInfoByIds(userIds))
                .build();
    }

    @PostMapping("/setObjectQuestionScore")
    @ApiOperation("设置考试记录的客观题得分,设置总分为逻辑得分+客观题")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "totalScore", value = "总成绩", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "examRecordId", value = "考试记录id", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "questionScores", value = "每题分数", required = true, dataType = "String", paramType = "query")
    })
    public CommonResult<Void> setObjectQuestionScore(@RequestBody HashMap map) {
        //从map中提取数据
        Integer totalScore = (Integer) map.get("totalScore");
        Integer examRecordId = (Integer) map.get("examRecordId");
        String questionScores = (String) map.get("questionScores");
        examRecordService.setObjectQuestionScore( totalScore, examRecordId, questionScores);
        return CommonResult.<Void>builder()
                .build();
    }

    @GetMapping("/getExamPassRate")
    @ApiOperation("提供每一门考试的通过率数据(echarts绘图)")
    public CommonResult<List<String>> getExamPassRate(HttpServletRequest request) {
        TokenVo userInfoByToken = JwtUtils.getUserInfoByToken(request);
        Integer classId = userInfoByToken.getClassId();
        if (userInfoByToken.getRoleId() == 1){
            if (userInfoByToken.getClassId() == null){
                throw new BusinessException(CommonErrorCode.E_1001231);
            }
        }
        if (userInfoByToken.getRoleId() == 2){
            if (userInfoByToken.getClassId() == null){
                throw new BusinessException(CommonErrorCode.E_1001231);
            }
        }
        if (userInfoByToken.getRoleId() == 3){
            classId =null;
        }
        return CommonResult.<List<String>>builder()
                .data(examService.getExamPassRateEchartData(classId))
                .build();
    }
    @GetMapping("/getExamPassRate2")
    @ApiOperation("提供每一门考试的通过率数据(echarts绘图)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, dataType = "int", paramType = "query"),
    })
    public CommonResult<List<String>> getExamPassRate2(@RequestParam(name = "userId") Integer userId) {
        return CommonResult.<List<String>>builder()
                .data(examService.getExamPassRateEchartData2(userId))
                .build();
    }

    @GetMapping("/getExamNumbers")
    @ApiOperation("提供每一门考试的考试次数(echarts绘图)")
    public CommonResult<List<String>> getExamNumbers(HttpServletRequest request) {
        TokenVo userInfoByToken = JwtUtils.getUserInfoByToken(request);
        Integer classId = userInfoByToken.getClassId();
        if (userInfoByToken.getRoleId() == 1){
            if (userInfoByToken.getClassId() == null){
                throw new BusinessException(CommonErrorCode.E_1001231);
            }
        }
        if (userInfoByToken.getRoleId() == 2){
            if (userInfoByToken.getClassId() == null){
                throw new BusinessException(CommonErrorCode.E_1001231);
            }
        }
        if (userInfoByToken.getRoleId() == 3){
            classId = null;
        }
        return CommonResult.<List<String>>builder()
                .data(examService.getExamNumbersEchartData(classId))
                .build();
    }



    @GetMapping("/getKmeansFx")
    @ApiOperation("数据分析")
    public CommonResult<Map<String,Object> > getKmeansFx() {
        //推荐数据集
        List<Map<String,Object>> list = new ArrayList<>();
        //聚类数据源
        List<Point> dataPoints = new ArrayList<>();
        //聚类数据中心
        List<Point> clusterCenters = new ArrayList<>();
        clusterCenters.add(new Point(1,0));
        clusterCenters.add(new Point(1,0.3));
        clusterCenters.add(new Point(1,0.7));
        String sql = "SELECT IFNULL(df,0) df,IFNULL(zf,0) zf,IFNULL(tf,0) tf,IFNULL(tg,0) tg,uid FROM (SELECT er.total_score df, e.total_score zf, e.pass_score tf, er.user_id uid, CASE WHEN ( er.total_score / e.pass_score ) >= 1 THEN 0 ELSE ROUND( 1- ( er.total_score / e.pass_score ), 2 ) END AS tg FROM exam_record er INNER JOIN exam e ON e.exam_id = er.exam_id) al";
        List<Map<String,Object>> dataList = dataMapper.ssql(sql);
        for (Map<String, Object> map : dataList) {
            dataPoints.add(new Point(1,MapUtils.getDouble(map,"tg")));
        }

        //通过聚类Kmeans算法获取聚类数据
        List<List<Point>> pv= KMeans.getV(3,10,dataPoints,clusterCenters);
        Map<String,Object> map = new HashMap<>();
        map.put("成绩优秀",pv.get(0).size());
        map.put("成绩中等",pv.get(1).size());
        map.put("成绩较差",pv.get(2).size());

        return CommonResult.<Map<String,Object> >builder()
                .data(map)
                .build();
    }



}
